package com.lagou.rpc.registry;

import com.lagou.rpc.config.ZkConfig;
import com.lagou.rpc.listener.NodeChangeListener;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;

import java.util.ArrayList;
import java.util.List;

/**
 * zookeeper注册工具类
 */
public class ZookeeperRegistry {

    private CuratorFramework client;
    private static final List<NodeChangeListener> listenerList = new ArrayList<>();

    public ZookeeperRegistry() {
        this.client = CuratorFrameworkFactory.newClient(ZkConfig.ZK_ADDRESS,
                ZkConfig.TIMEOUT, ZkConfig.TIMEOUT, new RetryNTimes(1, 1000));
        client.start();
    }

    public void registry(String serverAddress) {
        try {
            System.out.println("=======zookeeper注册开始======");
            //注册服务器临时节点到 /server 下
            client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(ZkConfig.SERVER_PATH + ZkConfig.SLASH + serverAddress);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(serverAddress + " 已上线提供服务");
    }

    public List<String> discovery() throws Exception {
        List<String> children = client.getChildren().forPath(ZkConfig.SERVER_PATH);
        registryCache();
        return children;
    }

    public void registryCache() {
        try {
            PathChildrenCache childrenCache = new PathChildrenCache(client, ZkConfig.SERVER_PATH, true);
            childrenCache.getListenable().addListener((curator, event) -> {
                listenerList.forEach(listener -> listener.update(event));
            });
            childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addListener(NodeChangeListener listener) {
        listenerList.add(listener);
    }
}
